using Assets.Scripts.Controllers;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Assets.Scripts.Entities
{
    internal class Throwable : MonoBehaviour, IPointerDownHandler
    {
        public event System.Action OnHold;
        public event System.Action OnRelease;

        public float maxChargeTime = 2f;
        [SerializeField] private float _distanceToMaxThrowForce = 3f;

        [Header("Direction line")]
        [SerializeField] private LineRenderer _lineRenderer;
        [SerializeField] private float _dotsPerUnit = 1f;
        [SerializeField] private float _direcationLineAnimationSpeed = 5f;

        private float ThrowForce => StatsController.Instance.MagicKickPower;
        private Rigidbody2D rb;

        private Vector2 _dragStartPosition;

        public void OnPointerDown(PointerEventData eventData)
        {
            _dragStartPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            Time.timeScale = .2f;
            _lineRenderer.enabled = true;
            OnHold?.Invoke();
        }

        void Start()
        {
            rb = GetComponent<Rigidbody2D>();
            _lineRenderer.positionCount = 2;
        }

        void Update()
        {
            if (Input.GetMouseButton(0) && _dragStartPosition != Vector2.zero)
            {
                var mousePosition = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
                var distance = Vector2.Distance(mousePosition, _dragStartPosition);
                distance = Mathf.Min(distance, _distanceToMaxThrowForce);

                // Calculate throw direction based on drag start and end positions
                Vector2 throwDirection = (mousePosition - _dragStartPosition).normalized;

                // Calculate the clamped throw distance based on charge time
                float clampedThrowDistance = 3 * Mathf.Clamp01(distance / _distanceToMaxThrowForce);

                // Update LineRenderer positions to visualize the throw direction and charge
                _lineRenderer.SetPosition(0, transform.position);
                _lineRenderer.SetPosition(1, (Vector2)transform.position - throwDirection * clampedThrowDistance);

                _lineRenderer.material.mainTextureScale = new Vector2(distance / _dotsPerUnit, 1);
                _lineRenderer.material.mainTextureOffset = new Vector2(_lineRenderer.material.mainTextureOffset.x - _direcationLineAnimationSpeed * Time.unscaledDeltaTime, 0);
            }

            if (Input.GetMouseButtonUp(0) && _dragStartPosition != Vector2.zero)
            {
                // Calculate direction based on mouse position
                Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                var distance = Vector2.Distance(mousePosition, _dragStartPosition);
                Vector2 throwDirection = (mousePosition - (Vector2)transform.position).normalized;

                // Calculate force based on charge time
                float finalThrowForce = ThrowForce * Mathf.Clamp01(distance / _distanceToMaxThrowForce);

                // Apply force to the Rigidbody in the opposite direction
                rb.AddForce(-throwDirection * finalThrowForce, ForceMode2D.Impulse);
                
                if (rb.angularVelocity < 10)
                {
                    rb.angularVelocity = Random.Range(-80, 80);
                }

                // Reset charge time
                _dragStartPosition = Vector2.zero;
                Time.timeScale = 1f;
                _lineRenderer.enabled = false;
                OnRelease?.Invoke();
            }
        }
    }
}
